package com.bajiao.third.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bajiao.common.util.AuthUtil;
import com.bajiao.common.util.Base64;
import com.bajiao.common.util.RedisUtil;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.enums.TradeType;
import com.ijpay.core.kit.HttpKit;
import com.ijpay.core.kit.IpKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.WxPayApiConfig;
import com.ijpay.wxpay.model.CloseOrderModel;
import com.ijpay.wxpay.model.RefundModel;
import com.ijpay.wxpay.model.TransferModel;
import com.ijpay.wxpay.model.UnifiedOrderModel;
import com.bajiao.common.exception.DataHandleException;
import com.bajiao.common.util.YuanCastFenUtil;
import com.bajiao.entity.pay.H5SceneInfo;
import com.bajiao.service.config.ConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HTTP;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * <P>
 * 用途:微信支付工具类
 * 1.本工具类中提到 URLEncoder 编码的参数都需要在调用时直接编码好。
 * 2.微信退款申请、退款回调通知、支付成功回调 appId可以用任意端的 只要和商户绑定即可。
 * </p>
 *
 * @author: FanJq
 * @create: 2024-10-10
 **/
@Slf4j
@Component
@Transactional(rollbackFor = Exception.class)
public class WxPayUtils {

    @Value("${bajiao.test-pay}")
    Integer testPay;

    @Value("${WXPayConfig.SPBILL_CREATE_IP}")
    public String SPBILL_CREATE_IP;

    @Autowired
    private ConfigService configService;

    @Resource
    private RedisUtil redisUtil;
    /**
     * 退款（该退款不是直接退款是申请退款，退款成功后会发起异步通知）
     * 获取支付配置时可以使用任何端的配置信息，只要当前项目中存在该配置就行。
     *
     * @param transactionId   微信交易号 微信支付成功是返回的参数 outTradeNo transactionId 二选一 (outTradeNo 微信统一下单时的outTradeNo)
     * @param outRefundNo     退款单号 例如退款记录的id
     * @param totalMoney      订单总金额（支付时支付的总金额，支付时如果是多订单支付时该金额为多个订单的总订单金额）
     * @param refundMoney     退款金额
     * @param refundNotifyUrl 退款成功后的回调地址
     * @return
     */
    public boolean refundMoney(String transactionId, String outRefundNo, String totalMoney, String refundMoney, String refundNotifyUrl) {
        //判断是否是测试支付
        if (testPay == 1) {
            totalMoney = "0.01";
            refundMoney = "0.01";
        }
        totalMoney = new BigDecimal(totalMoney).multiply(new BigDecimal("100")).stripTrailingZeros().toPlainString();
        refundMoney = new BigDecimal(refundMoney).multiply(new BigDecimal("100")).stripTrailingZeros().toPlainString();
        WxPayApiConfig wxPayApiConfig = configService.getWxPayApiConfig("wxApp");
        Map<String, String> params = RefundModel.builder()
                .appid(wxPayApiConfig.getAppId())
                .mch_id(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .transaction_id(transactionId)
                .out_refund_no(outRefundNo)
                .total_fee(totalMoney)
                .refund_fee(refundMoney)
                .notify_url(refundNotifyUrl)
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5);
        String refundStr = WxPayApi.orderRefund(false, params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId());
        log.info(refundStr);
        Map<String, String> result = WxPayKit.xmlToMap(refundStr);

        String returnCode = result.get("return_code");
        String returnMsg = result.get("return_msg");
        if (!WxPayKit.codeIsOk(returnCode)) {
            throw new DataHandleException(returnMsg);
        }
        log.info("refundStr: {}", refundStr);
        return true;
    }


    /**
     * app支付
     *
     * @param request
     * @param outTradeNo 数据源id（用来表示支付的那个条数据） 该参数的数据只能使用一次，以订单举例 订单id记录中新增一个字段支付id 每次对该订单支付时随机生成一个id。多个订单一起支付时这个id需相同。
     * @param money      支付金额
     * @param body       商品信息
     * @param notifyUrl  回调地址
     * @param params     支付成功回调中的参数 （可以是任何数据） 建议进行编码 例如  URLEncoder.encode(paramsStr, "utf-8")
     * @return
     */
    public String payApp(HttpServletRequest request, String outTradeNo, String money, String body, String notifyUrl, String params) {
        money = testPay == 1 ? "0.01" : money;

        //支付金额转成分
        money = YuanCastFenUtil.cast(money);

        WxPayApiConfig wxPayApiConfig = configService.getWxPayApiConfig("wxApp");

        String ip = IpKit.getRealIp(request);
        if (StringUtils.isBlank(ip)) {
            ip = "127.0.0.1";
        }

        Map<String, String> payParamsMap = UnifiedOrderModel
                .builder()
                .appid(wxPayApiConfig.getAppId())
                .mch_id(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .body(body)
                //微信自定义参数 最大长度127
                .attach(params)
                .out_trade_no(outTradeNo)
                .total_fee(money)
                .spbill_create_ip(ip)
                .notify_url(notifyUrl)
                .trade_type(TradeType.APP.getTradeType())
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

        String xmlResult = WxPayApi.pushOrder(false, payParamsMap);

        log.info(xmlResult);
        Map<String, String> result = WxPayKit.xmlToMap(xmlResult);

        String returnCode = result.get("return_code");
        String returnMsg = result.get("return_msg");
        if (!WxPayKit.codeIsOk(returnCode)) {
            throw new DataHandleException(returnMsg);
        }
        String resultCode = result.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode)) {
            throw new DataHandleException(returnMsg);
        }
        // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回
        String prepayId = result.get("prepay_id");

        Map<String, String> packageParams = WxPayKit.appPrepayIdCreateSign(wxPayApiConfig.getAppId(), wxPayApiConfig.getMchId(), prepayId,
                wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

        String jsonStr = JSON.toJSONString(packageParams);
        log.info("返回apk的参数:" + jsonStr);
        return jsonStr;
    }

    /**
     * 小程序支付
     *
     * @param request
     * @param openId     小程序的openId
     * @param outTradeNo 数据源id（用来表示支付的那个条数据） 该参数的数据只能使用一次，以订单举例 订单id记录中新增一个字段支付id 每次对该订单支付时随机生成一个id。多个订单一起支付时这个id需相同。
     * @param money      支付金额
     * @param body       商品信息
     * @param notifyUrl  回调地址
     * @param params     支付成功回调中的参数 （可以是任何数据） 建议进行编码 例如  URLEncoder.encode(paramsStr, "utf-8")
     * @return
     */
    public String miniAppPay(HttpServletRequest request, String openId, String outTradeNo, String money, String body, String notifyUrl, String params) {
        money = testPay == 1 ? "0.01" : money;
        //支付金额转成分
        money = YuanCastFenUtil.cast(money);
        WxPayApiConfig wxPayApiConfig = configService.getWxPayApiConfig("wxMiniApp");
        String ip = IpKit.getRealIp(request);
        if (StringUtils.isBlank(ip)) {
            ip = "127.0.0.1";
        }
        Map<String, String> payParamsMap = UnifiedOrderModel
                .builder()
                .appid(wxPayApiConfig.getAppId())
                .mch_id(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .body(body)
                //微信自定义参数 最大长度127
                .attach(params)
                .out_trade_no(outTradeNo)
                .total_fee(money)
                .spbill_create_ip(ip)
                .notify_url(notifyUrl)
                .trade_type(TradeType.JSAPI.getTradeType())
                .openid(openId)
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);
        String xmlResult = WxPayApi.pushOrder(false, payParamsMap);
        log.info(xmlResult);
        Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
        String returnCode = result.get("return_code");
        String returnMsg = result.get("return_msg");
        if (!WxPayKit.codeIsOk(returnCode))
            throw new DataHandleException(returnMsg);
        String resultCode = result.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode))
            throw new DataHandleException(returnMsg);
        // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回
        String prepayId = result.get("prepay_id");
        Map<String, String> packageParams = new HashMap<>();
        try {
            packageParams = WxPayKit.miniAppPrepayIdCreateSign(wxPayApiConfig.getAppId(), prepayId,
                    wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);
        }catch (Exception e) {
            e.printStackTrace();
            throw new DataHandleException("签名失败");
        }
        String jsonStr = JSON.toJSONString(packageParams);
        log.info("小程序支付的参数:" + jsonStr);
        return jsonStr;
    }


    /**
     * 获取h5支付 跳转页面
     * appId为微信分配的公众账号ID（企业号corpid即为此appId）
     * 这块处理建议参考 该文档 https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_4
     *
     * @param request
     * @param outTradeNo  数据源id（用来表示支付的那个条数据） 该参数的数据只能使用一次，以订单举例 订单id记录中新增一个字段支付id 每次对该订单支付时随机生成一个id。多个订单一起支付时这个id需相同。
     * @param money       支付金额
     * @param body        商品信息
     * @param notifyUrl   回调地址
     * @param redirectUrl 前端支付成功跳转路径 需要在 商户平台---产品中心--开发配置中配置一下。 心必须进行 URLEncoder.encode("http://xxxx.xxx.xxx", "utf-8") 跳转后的建议建议弹出是否已支付完成的询问框
     * @param wapUrl      h5项目的域名 例如 https://xxx.xx.xx 这路径。需要在 商户平台---产品中心--开发配置中配置一下。
     * @param wapName     h5项目的名称 随便起（是显示在微信支付页面上的）
     * @param params      支付成功回调中的参数 （可以是任何数据） 建议进行编码 例如  URLEncoder.encode(paramsStr, "utf-8")
     * @return
     */
    public String payH5(HttpServletRequest request, String outTradeNo, String money, String body, String notifyUrl, String redirectUrl, String wapUrl, String wapName, String params) {
        if (testPay == 1) {
            money = "0.01";
        }

        //支付金额转成分
        money = YuanCastFenUtil.cast(money);

        WxPayApiConfig wxPayApiConfig = configService.getWxPayApiConfig("wxWeb");

        String ip = IpKit.getRealIp(request);
        if (StringUtils.isBlank(ip)) {
            ip = "127.0.0.1";
        }

        H5SceneInfo sceneInfo = new H5SceneInfo();

        H5SceneInfo.H5 h5_info = new H5SceneInfo.H5();
        h5_info.setType("Wap");

        //此域名必须在商户平台--"产品中心"--"开发配置"中添加
        h5_info.setWap_url(wapUrl);
        h5_info.setWap_name(wapName);
        sceneInfo.setH5Info(h5_info);

        Map<String, String> payParamsMap = UnifiedOrderModel
                .builder()
                .appid(wxPayApiConfig.getAppId())
                .mch_id(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .body(body)
                //微信自定义参数 最大长度127
                .attach(params)
                .out_trade_no(outTradeNo)
                .total_fee(money)
                .spbill_create_ip(ip)
                .notify_url(notifyUrl)
                .trade_type(TradeType.JSAPI.getTradeType())
                .scene_info(JSON.toJSONString(sceneInfo))
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

        String xmlResult = WxPayApi.pushOrder(false, payParamsMap);

        log.info(xmlResult);
        Map<String, String> result = WxPayKit.xmlToMap(xmlResult);

        String returnCode = result.get("return_code");
        String returnMsg = result.get("return_msg");
        if (!WxPayKit.codeIsOk(returnCode)) {
            throw new DataHandleException(returnMsg);
        }
        String resultCode = result.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode)) {
            throw new DataHandleException(returnMsg);
        }
        // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回
        String prepayId = result.get("prepay_id");

        String webUrl = result.get("mweb_url");
        log.info("prepay_id:" + prepayId + " mweb_url:" + webUrl);
        return webUrl + "&redirect_url=" + redirectUrl;
    }

    /**
     * 公众号支付
     *
     * @param request
     * @param openId     公众号的openId
     * @param outTradeNo 数据源id（用来表示支付的那个条数据） 该参数的数据只能使用一次，以订单举例 订单id记录中新增一个字段支付id 每次对该订单支付时随机生成一个id。多个订单一起支付时这个id需相同。
     * @param money      支付金额
     * @param body       商品信息
     * @param notifyUrl  回调地址
     * @param params     支付成功回调中的参数 （可以是任何数据） 建议进行编码 例如  URLEncoder.encode(paramsStr, "utf-8")
     * @return
     */
    public String webPay(HttpServletRequest request, String openId, String outTradeNo, String money, String body, String notifyUrl, String params) {
        if (testPay == 1) {
            money = "0.01";
        }

        //支付金额转成分
        money = YuanCastFenUtil.cast(money);

        WxPayApiConfig wxPayApiConfig = configService.getWxPayApiConfig("wxWeb");

        String ip = IpKit.getRealIp(request);
        if (StringUtils.isBlank(ip)) {
            ip = "127.0.0.1";
        }

        Map<String, String> payParamsMap = UnifiedOrderModel
                .builder()
                .appid(wxPayApiConfig.getAppId())
                .mch_id(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .body(body)
                //微信自定义参数 最大长度127
                .attach(params)
                .out_trade_no(outTradeNo)
                .total_fee(money)
                .spbill_create_ip(ip)
                .notify_url(notifyUrl)
                .trade_type(TradeType.JSAPI.getTradeType())
                .openid(openId)
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

        String xmlResult = WxPayApi.pushOrder(false, payParamsMap);

        log.info(xmlResult);
        Map<String, String> result = WxPayKit.xmlToMap(xmlResult);

        String returnCode = result.get("return_code");
        String returnMsg = result.get("return_msg");
        if (!WxPayKit.codeIsOk(returnCode)) {
            throw new DataHandleException(returnMsg);
        }
        String resultCode = result.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode)) {
            throw new DataHandleException(returnMsg);
        }
        // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回
        String prepayId = result.get("prepay_id");

        Map<String, String> packageParams = WxPayKit.appPrepayIdCreateSign(wxPayApiConfig.getAppId(), wxPayApiConfig.getMchId(), prepayId,
                wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

        String jsonStr = JSON.toJSONString(packageParams);
        log.info("公众号支付的参数:" + jsonStr);
        return jsonStr;
    }


    /**
     * 微信退款通知(解析通知中的加密数据)
     * 获取支付配置时可以使用任何端的配置信息，只要当前项目中存在该配置就行。
     *
     * @param request
     * @return
     */
    public String refundNotify(HttpServletRequest request) {
        String xmlMsg = HttpKit.readData(request);
        log.info("退款通知=" + xmlMsg);
        Map<String, String> params = WxPayKit.xmlToMap(xmlMsg);

        String returnCode = params.get("return_code");
        String decryptData = "";
        // 注意重复通知的情况，同一订单号可能收到多次通知，请注意一定先判断订单状态
        if (WxPayKit.codeIsOk(returnCode)) {
            WxPayApiConfig wxPayApiConfig = configService.getWxPayApiConfig("wxApp");
            String reqInfo = params.get("req_info");
            decryptData = WxPayKit.decryptData(reqInfo, wxPayApiConfig.getPartnerKey());
            log.info("退款通知解密后的数据=" + decryptData);
        }
        return decryptData;
    }

    /**
     * 获取扫描支付 二维码
     * 采用的扫描支付模式二
     *
     * @param request
     * @param outTradeNo 数据源id（用来表示支付的那个条数据） 该参数的数据只能使用一次，以订单举例 订单id记录中新增一个字段支付id 每次对该订单支付时随机生成一个id。多个订单一起支付时这个id需相同。
     * @param money      支付金额
     * @param body       商品信息
     * @param notifyUrl  回调地址
     * @param params     支付成功回调中的参数 （可以是任何数据） 建议进行编码 例如  URLEncoder.encode(paramsStr, "utf-8")
     * @return
     */
    public String scanCode(HttpServletRequest request, String outTradeNo, String money, String body, String notifyUrl, String params) {
        if (testPay == 1) {
            money = "0.01";
        }

        //支付金额转成分
        money = YuanCastFenUtil.cast(money);

        WxPayApiConfig wxPayApiConfig = configService.getWxPayApiConfig("wxApp");
        String ip = IpKit.getRealIp(request);
        if (StringUtils.isBlank(ip)) {
            ip = "127.0.0.1";
        }
        Map<String, String> payParamsMap = UnifiedOrderModel
                .builder()
                .appid(wxPayApiConfig.getAppId())
                .mch_id(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .body(body)
                .attach(params)
                .out_trade_no(outTradeNo)
                .total_fee(money)
                .spbill_create_ip(ip)
                .notify_url(notifyUrl)
                .trade_type(TradeType.NATIVE.getTradeType())
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

        String xmlResult = WxPayApi.pushOrder(false, payParamsMap);
        log.info("统一下单:" + xmlResult);

        Map<String, String> result = WxPayKit.xmlToMap(xmlResult);

        String returnCode = result.get("return_code");
        String returnMsg = result.get("return_msg");
        System.out.println(returnMsg);
        if (!WxPayKit.codeIsOk(returnCode)) {
            throw new DataHandleException(returnMsg);
        }
        String resultCode = result.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode)) {
            throw new DataHandleException(returnMsg);
        }
        //生成预付订单success
        return result.get("code_url");
    }

    /**
     * 解析支付回调通知 数据
     *
     * @param request
     * @return
     */
    public Map payNotify(HttpServletRequest request) {

        WxPayApiConfig wxPayApiConfig = configService.getWxPayApiConfig("wxApp");

        String xmlMsg = HttpKit.readData(request);
        log.info("支付通知=" + xmlMsg);
        Map<String, String> params = WxPayKit.xmlToMap(xmlMsg);

        String returnCode = params.get("return_code");

        // 注意重复通知的情况，同一订单号可能收到多次通知，请注意一定先判断订单状态
        // 注意此处签名方式需与统一下单的签名类型一致
        if (!WxPayKit.verifyNotify(params, wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256)) {
            throw new DataHandleException("验签失败");
        }
        return params;
    }

    /**
     * 单笔转账到零钱(需要开通该功能才能使用)
     *
     * @param outTradeNo 商户端的唯一订单号(可以为提现的id)
     * @param money      转账金额
     * @param openId     账号
     * @param remark     备注、描述
     * @return
     */
    public boolean transfer(HttpServletRequest request, String outTradeNo, String money, String openId, String remark) {
        //TODO 这里的appid可以是申请商户号的appid或商户号绑定的appid。这里使用app应用的
        WxPayApiConfig wxPayApiConfig = configService.getWxPayApiConfig("wxApp");

        String ip = IpKit.getRealIp(request);
        if (StringUtils.isBlank(ip)) {
            ip = "127.0.0.1";
        }

        //转账金额转成分
        money = YuanCastFenUtil.cast(money);

        Map<String, String> params = TransferModel.builder()
                .mch_appid(wxPayApiConfig.getAppId())
                .mchid(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .partner_trade_no(outTradeNo)
                .openid(openId)
                /**
                 *  校验用户姓名选项
                 * 	NO_CHECK：不校验真实姓名
                 *  FORCE_CHECK：强校验真实姓名
                 */
                .check_name("NO_CHECK")
                .amount(money)
                .desc(remark)
                .spbill_create_ip(ip)
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5, false);

        // 提现
        String transfers = WxPayApi.transfers(params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId());
        log.info("提现结果:" + transfers);
        Map<String, String> map = WxPayKit.xmlToMap(transfers);
        String returnCode = map.get("return_code");
        String resultCode = map.get("result_code");
        if (WxPayKit.codeIsOk(returnCode) && WxPayKit.codeIsOk(resultCode)) {
            // 提现成功
            return true;
        } else {
            // 提现失败
            return false;
        }
    }

    /**
     * 关闭订单(订单超时未支付、更换别的支付方式时调用该方法)
     *
     * @param outTradeNo 统一下单时传入的参数，可以是付款编号或订单编号，商品订单为付款编号
     * @return
     */
    public void tradeClose(String outTradeNo) {
        WxPayApiConfig wxPayApiConfig = configService.getWxPayApiConfig("wxApp");

        Map<String, String> params = CloseOrderModel.builder()
                .appid(wxPayApiConfig.getAppId())
                .mch_id(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .out_trade_no(outTradeNo)
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5, false);
        WxPayApi.closeOrder(params);
    }

    public String getWxAccessToken(){
        String redisKey = "wx_access_token";
        if(redisUtil.hasKey(redisKey)){
            return redisUtil.get(redisKey).toString();
        }
        Map<String, String> wxMiniConfig = configService.getWxMiniConfig();
        String appId = wxMiniConfig.get("appId");
        String secret = wxMiniConfig.get("appSecret");
        String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appId+"&secret="+secret;
        String result = AuthUtil.httpRequest(accessTokenUrl, "GET", null);
        JSONObject json = JSONObject.parseObject(result);
        String access_token = String.valueOf(json.get("access_token"));
        Long expires_in = Long.valueOf(String.valueOf(json.get("expires_in")));
        if(StringUtils.isEmpty(access_token)){
            access_token="";
        }
        // 存redis, 过期时间为7200秒
        redisUtil.set(redisKey,access_token,expires_in);
        return access_token;
    }

    /**
     * @Description
     * 获取不限制的小程序码
     * @date 2023/11/18 14:26
     * @author FanJq
     * @return {@link String}
     */
    public String getUnlimitedQRCode(String inviteCode){
        String scene = "a=" + inviteCode;
        String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + getWxAccessToken();
        Map<String, String> wxMiniConfig = configService.getWxMiniConfig();
        JSONObject jsonParam = new JSONObject();
        jsonParam.put("scene", scene);
        jsonParam.put("env_version", wxMiniConfig.get("envVersion"));
        //jsonParam.put("page", "pages/tabBar/home");
        jsonParam.put("check_path", false);
        InputStream stream = doWXPost(url, jsonParam);
        String base64 = Base64.inputStream2Base64(stream);
        return base64;
    }

    /**
     *  请求
     * @param url
     * @param jsonParam
     * @return
     */
    public static InputStream doWXPost(String url, JSONObject jsonParam) {
        InputStream instreams = null;
        HttpPost httpRequest = new HttpPost(url);// 创建HttpPost对象
        try {
            StringEntity se = new StringEntity(jsonParam.toString(),"utf-8");
            se.setContentType("application/json");
            se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,"UTF-8"));
            httpRequest.setEntity(se);
            HttpResponse httpResponse = new DefaultHttpClient().execute(httpRequest);
            if (httpResponse.getStatusLine().getStatusCode() == 200) {
                HttpEntity httpEntity = httpResponse.getEntity();
                if (httpEntity != null) {
                    instreams = httpEntity.getContent();
                }
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return instreams;
    }
}
